home *** CD-ROM | disk | FTP | other *** search
-
-
- /*
- Floating point package support routines
-
- Note the "fp" library function, available in DEFF2.CRL,
- is used extensively by all the floating point number
- crunching functions.
-
- (see FLOAT.DOC for details...)
-
- NEW FEATURE: a special "printf" function has been included
- in this source file for use with floating point
- operands, in addition to the normal types. The
- printf presented here will take precedence over
- the DEFF.CRL version when "float" is specified
- on the CLINK command line at linkage time.
- Note that the "fp" function, needed by most of
- the functions in this file, resides in DEFF2.CRL
- and will be automatically collected by CLINK.
-
- All functions here written by Bob Mathias, except printf and
- _spr (written by Leor Zolman.)
- */
-
- #include "bdscio.h"
-
- #define NORM_CODE 0
- #define ADD_CODE 1
- #define SUB_CODE 2
- #define MULT_CODE 3
- #define DIV_CODE 4
- #define FTOA_CODE 5
-
- fpcomp(op1,op2)
- char *op1,*op2;
- {
- char work[5];
- fpsub(work,op1,op2);
- if (work[3] > 127) return (-1);
- if (work[0]+work[1]+work[2]+work[3]) return (1);
- return (0);
- }
-
- fpnorm(op1) char *op1;
- { fp(NORM_CODE,op1,op1);return(op1);}
-
- fpadd(result,op1,op2)
- char *result,*op1,*op2;
- { fp(ADD_CODE,result,op1,op2);return(result);}
-
- fpsub(result,op2,op1)
- char *result,*op1,*op2;
- {fp(SUB_CODE,result,op1,op2);return(result);}
-
- fpmult(result,op1,op2)
- char *result,*op1,*op2;
- { fp(MULT_CODE,result,op1,op2);return(result);}
-
- fpdiv(result,op1,op2)
- char *result,*op1,*op2;
- { fp(DIV_CODE,result,op1,op2);return(result);}
-
- atof(fpno,s)
- char fpno[5],*s;
- {
- char *fpnorm(),work[5],ZERO[5],FP_10[5];
- int sign_boolean,power;
-
- initb(FP_10,"0,0,0,80,4");
- setmem(fpno,5,0);
- sign_boolean=power=0;
-
- while (*s==' ' || *s=='\t') ++s;
- if (*s=='-'){sign_boolean=1;++s;}
- for (;isdigit(*s);++s){
- fpmult(fpno,fpno,FP_10);
- work[0]=*s-'0';
- work[1]=work[2]=work[3]=0;work[4]=31;
- fpadd(fpno,fpno,fpnorm(work));
- }
- if (*s=='.'){
- ++s;
- for (;isdigit(*s);--power,++s){
- fpmult(fpno,fpno,FP_10);
- work[0]=*s-'0';
- work[1]=work[2]=work[3]=0;work[4]=31;
- fpadd(fpno,fpno,fpnorm(work));
- }
- }
- if (toupper(*s) == 'E') {++s; power += atoi(s); }
- if (power>0)
- for (;power!=0;--power) fpmult(fpno,fpno,FP_10);
- else
- if (power<0)
- for (;power!=0;++power) fpdiv(fpno,fpno,FP_10);
- if (sign_boolean){
- setmem(ZERO,5,0);
- fpsub(fpno,ZERO,fpno);
- }
- return(fpno);
- }
- ftoa(result,op1)
- char *result,*op1;
- { fp(FTOA_CODE,result,op1);return(result);}
-
- itof(op1,n)
- char *op1;
- int n;
- {
- char temp[20];
- return atof(op1, itoa(temp,n));
- }
-
- itoa(str,n)
- char *str;
- {
- char *sptr;
- sptr = str;
- if (n<0) { *sptr++ = '-'; n = -n; }
- _uspr(&sptr, n, 10);
- *sptr = '\0';
- return str;
- }
-
-
- /*
- The short "printf" function given here is exactly the
- same as the one in the library, but it needs to be placed
- here so that the special "_spr" is used instead of the
- normal one in DEFF.CRL. The way the linker works is that
- a function is not linked in UNTIL IT IS REFERENCED...so
- if the definition of "printf" were not placed here in this
- file, "_spr" would not be referenced at all
- until the "printf" from DEFF.CRL got yanked in, at which time
- "_spr" would ALSO be taken from DEFF.CRL and cause the
- floating point "_spr" options to not be recognized.
-
- In other words, if "printf" were not given explicitly here,
- the WRONG _spr would end up being used.
- */
-
-
- printf(format)
- char *format;
- {
- char line[MAXLINE];
- _spr(line,&format); /* use "_spr" to form the output */
- puts(line); /* and print out the line */
- }
-
-
- /*
- This is the special formatting function, which supports the
- "e" and "f" conversions as well as the normal "d", "s", etc.
- When using "e" or "f" format, the corresponding argument in
- the argument list should be a pointer to one of the five-byte
- strings used as floating point numbers by the floating point
- functions. Note that you don't need to ever use the "ftoa"
- function when using this special printf/sprintf combination;
- to achieve the same result as ftoa, a simple "%e" format
- conversion will do the trick. "%f" is used to eliminate the
- scientific notation and set the precision. The only [known]
- difference between the "e" and "f" conversions as used here
- and the ones described in the Kernighan & Ritchie book is that
- ROUNDING does not take place in this version...e.g., printing
- a floating point number which happens to equal exactly 3.999
- using a "%5.2f" format conversion will produce " 3.99" instead
- of " 4.00".
- */
-
-
- _spr(line,fmt)
- char *line, **fmt;
- {
- char _uspr(), c, base, *sptr, *format;
- char wbuf[80], *wptr, pf, ljflag;
- int width, precision, exp, *args;
-
- format = *fmt++; /* fmt first points to the format string */
- args = fmt; /* now fmt points to the first arg value */
- while (c = *format++)
- if (c == '%') {
- wptr = wbuf;
- precision = 6;
- ljflag = pf = 0;
-
- if (*format == '-') {
- format++;
- ljflag++;
- }
-
- if ( !(width = _gv2(&format))) width++;
-
- if ((c = *format++) == '.') {
- precision = _gv2(&format);
- pf++;
- c = *format++;
- }
-
- switch(toupper(c)) {
- case 'E': if (precision>7) precision = 7;
- ftoa(wbuf,*args++);
- strcpy(wbuf+precision+3, wbuf+10);
- width -= strlen(wbuf);
- goto pad2;
-
- case 'F': ftoa(&wbuf[60],*args++);
- sptr = &wbuf[60];
- while ( *sptr++ != 'E')
- ;
- exp = atoi(sptr);
- sptr = &wbuf[60];
- if (*sptr == ' ') sptr++;
- if (*sptr == '-') {
- *wptr++ = '-';
- sptr++;
- width--;
- }
- sptr += 2;
-
- if (exp < 1) {
- *wptr++ = '0';
- width--;
- }
-
- pf = 7;
- while (exp > 0 && pf) {
- *wptr++ = *sptr++;
- pf--;
- exp--;
- width--;
- }
-
- while (exp > 0) {
- *wptr++ = '0';
- exp--;
- width--;
- }
-
- *wptr++ = '.';
- width--;
-
- while (exp < 0 && precision) {
- *wptr++ = '0';
- exp++;
- precision--;
- width--;
- }
-
- while (precision && pf) {
- *wptr++ = *sptr++;
- pf--;
- precision--;
- width--;
- }
-
- while (precision>0) {
- *wptr++ = '0';
- precision--;
- width--;
- }
-
- goto pad;
-
-
- case 'D': if (*args < 0) {
- *wptr++ = '-';
- *args = -*args;
- width--;
- }
- case 'U': base = 10; goto val;
-
- case 'X': base = 16; goto val;
-
- case 'O': base = 8;
-
- val: width -= _uspr(&wptr,*args++,base);
- goto pad;
-
- case 'C': *wptr++ = *args++;
- width--;
- goto pad;
-
- case 'S': if (!pf) precision = 200;
- sptr = *args++;
- while (*sptr && precision) {
- *wptr++ = *sptr++;
- precision--;
- width--;
- }
-
- pad: *wptr = '\0';
- pad2: wptr = wbuf;
- if (!ljflag)
- while (width-- > 0)
- *line++ = ' ';
-
- while (*line = *wptr++)
- line++;
-
- if (ljflag)
- while (width-- > 0)
- *line++ = ' ';
- break;
-
- default: *line++ = c;
-
- }
- }
- else *line++ = c;
-
- *line = '\0';
- }